using System;
using System.Net.Sockets;
using System.Text;
using UnityEngine;

/*
 * MarkerBasedSocketManager - 基于标记的Socket管理器
 * 
 * 功能：
 * 1. 使用特定标记分割消息
 * 2. 处理不完整消息的拼接
 * 3. 实现基于标记的消息确认机制
 * 
 * 版本：1.0
 * 作者：yixiang.hui
 * 创建时间：2025.9.4
 * 最后修改：2025.9.4
 */

namespace HyxFrame.Core
{
    /// <summary>
    /// 基于标记的Socket管理器，使用特定标记来分割消息
    /// </summary>
    public class MarkerBasedSocketManager : SocketManagerBase
    {
        #region 常量定义
        
        /// <summary>
        /// 服务器消息结束标记
        /// </summary>
        private const string SERVER_END_MARKER = "sr_end_sr";
        
        /// <summary>
        /// 客户端消息结束标记
        /// </summary>
        private const string CLIENT_END_MARKER = "cl_end_cl";
        
        #endregion
        
        #region 私有字段
        
        /// <summary>
        /// 不完整消息缓冲区
        /// </summary>
        private StringBuilder incompleteMessage = new StringBuilder();
        
        #endregion
        
        #region 消息处理实现
        
        /// <summary>
        /// 处理接收到的数据，基于标记分割完整消息
        /// </summary>
        /// <param name="data">接收到的字节数组</param>
        /// <param name="bytesRead">实际读取的字节数</param>
        protected override void ProcessReceivedData(byte[] data, int bytesRead)
        {
            // 将接收到的字节数组转换为UTF8字符串
            string receivedData = Encoding.UTF8.GetString(data, 0, bytesRead);
            
            // 将接收到的数据追加到不完整消息缓冲区
            incompleteMessage.Append(receivedData);
            
            // 当不完整消息中包含服务器结束标记时，循环处理完整消息
            while (incompleteMessage.ToString().Contains(SERVER_END_MARKER))
            {
                // 查找结束标记的位置
                int endIndex = incompleteMessage.ToString().IndexOf(SERVER_END_MARKER);
                
                // 提取从开始到结束标记之间的完整消息
                string fullMessage = incompleteMessage.ToString().Substring(0, endIndex);
                
                // 从缓冲区中移除已处理的消息和结束标记
                incompleteMessage.Remove(0, endIndex + SERVER_END_MARKER.Length);
                
                // 检查消息是否为确认消息(ACK)
                if (fullMessage.StartsWith("ACK:"))
                {
                    // 处理确认消息
                    HandleAcknowledgment(fullMessage);
                }
                else
                {
                    // 处理普通消息
                    HandleMessage(fullMessage);
                    
                    // 发送确认消息
                    SendAcknowledgment(fullMessage);
                }
            }
        }
        
        /// <summary>
        /// 格式化发送消息，添加消息ID和结束标记
        /// </summary>
        /// <param name="message">原始消息</param>
        /// <param name="messageId">消息ID</param>
        /// <returns>格式化后的字节数组</returns>
        protected override byte[] FormatSendMessage(string message, int messageId)
        {
            string formattedMessage = $"{messageId}:{message}{CLIENT_END_MARKER}";
            return Encoding.UTF8.GetBytes(formattedMessage);
        }
        
        /// <summary>
        /// 发送确认消息
        /// </summary>
        /// <param name="message">需要确认的原始消息</param>
        protected override void SendAcknowledgment(string message)
        {
            try
            {
                string[] parts = message.Split(':');
                if (parts.Length >= 1 && int.TryParse(parts[0], out int messageId))
                {
                    string ackMessage = $"ACK:{messageId}{CLIENT_END_MARKER}";
                    byte[] ackBytes = Encoding.UTF8.GetBytes(ackMessage);
                    
                    // 异步发送确认消息
                    socket.BeginSend(ackBytes, 0, ackBytes.Length, SocketFlags.None, null, socket);
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"发送确认失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 处理接收到的消息
        /// </summary>
        /// <param name="acknowledgment">消息内容</param>
        protected override void HandleMessage(string acknowledgment)
        {
            base.HandleMessage(acknowledgment);
            Debug.Log($"接收到完整消息: {acknowledgment}");
        }
        
        #endregion
    }
}